<template>
  <div class="pdf-viewer-container">
    <!-- 缩略图侧边栏 -->
    <div class="thumbnail-sidebar" :class="{ collapsed: sidebarCollapsed }">
      <div class="sidebar-header">
        <span>缩略图</span>
        <button class="toggle-btn" @click="sidebarCollapsed = !sidebarCollapsed">
          {{ sidebarCollapsed ? '▶' : '◀' }}
        </button>
      </div>
      <div class="thumbnail-container" v-show="!sidebarCollapsed">
        <div
          v-for="page in pdf_pages"
          :key="'thumb-' + page"
          class="thumbnail-item"
          :class="{ 'active-thumbnail': page === currentPage }"
          @click="goToPage(page)"
        >
          <canvas :id="'thumbnail_' + page"></canvas>
          <div class="page-number">{{ page }}</div>
        </div>
      </div>
    </div>

    <!-- 主内容区 -->
    <div class="main-content" :style="{ 'margin-left': sidebarCollapsed ? '40px' : '210px' }">
      <!-- 顶部导航栏 -->
      <div class="pdf-nav">
        <div class="nav-controls">
          <button class="nav-button" @click="prePage" :disabled="currentPage === 1">
            <i class="icon">←</i> 上一页
          </button>
          <span class="page-info">
            <input
              type="number"
              v-model.number="currentPage"
              @change="goToPage"
              min="1"
              :max="pdf_pages"
            />
            / {{ pdf_pages }}
          </span>
          <button class="nav-button" @click="nextPage" :disabled="currentPage === pdf_pages">
            下一页 <i class="icon">→</i>
          </button>
        </div>
        <div class="zoom-controls">
          <button class="zoom-button" @click="scaleX" :disabled="pdf_scale <= 0.5">
            <i class="icon">−</i>
          </button>
          <span class="zoom-percent">{{ Math.round(pdf_scale * 100) }}%</span>
          <button class="zoom-button" @click="scaleD" :disabled="pdf_scale >= 2.0">
            <i class="icon">+</i>
          </button>
        </div>
      </div>

      <!-- PDF页面显示区 -->
      <div class="pdf-content" :style="{ width: pdf_div_width }">
        <canvas
          v-for="page in pdf_pages"
          :id="'the_canvas' + page"
          :key="page"
          :class="{ 'active-page': page === currentPage }"
        ></canvas>
      </div>
    </div>
  </div>
</template>

<script>
import { useRoute } from 'vue-router'
import axios from 'axios'
import * as PDFJS from 'pdfjs-dist'
import PdfWorker from 'pdfjs-dist/build/pdf.worker.min.mjs?worker'

PDFJS.GlobalWorkerOptions.workerPort = new PdfWorker()

export default {
  name: 'PdfView',
  props: {
    data: ArrayBuffer
  },
  data() {
    return {
      pdf_scale: 1.0,
      pdf_pages: [],
      pdf_div_width: '',
      currentPage: 1,
      loading: false,
      sidebarCollapsed: false,
      thumbnailScale: 0.2
    }
  },
  computed: {
    fileUrl() {
      const { query } = useRoute()
      if (query?.url) {
        return query?.url
      }
      const urlstrs = window.location.href.match(new RegExp('[?&]' + 'url' + '=([^&/#]+)', 'i'))
      return this.url || (urlstrs[1] ? decodeURIComponent(urlstrs[1]) : '')
    }
  },
  watch: {
    currentPage(newVal) {
      if (newVal < 1) this.currentPage = 1
      if (newVal > this.pdf_pages) this.currentPage = this.pdf_pages
    }
  },
  mounted() {
    const url = this.fileUrl || '/data/file/CCAR66-R3基础执照英语参考教材（中英文对照版第一册）.pdf'
    axios
      .get(url, {
        responseType: 'blob'
      })
      .then(async (res) => {
        const arrayBuffer = await this.readBuffer(this.blobToFile(res.data, 'fileName.pdf'))
        this.loadFile(arrayBuffer)
      })
      .finally(() => {
        this.loading = false
      })
  },
  methods: {
    async readBuffer(file) {
      return new Promise((resolve, reject) => {
        const reader = new FileReader()
        reader.onload = (loadEvent) => resolve(loadEvent.target.result)
        reader.onerror = (e) => reject(e)
        reader.readAsArrayBuffer(file)
      })
    },
    blobToFile(blob, fileName) {
      const type = blob.type
      const file = new File([blob], fileName, { type })
      return file
    },
    scaleD() {
      if (this.pdf_scale >= 2.0) return
      this.pdf_scale = +(this.pdf_scale + 0.1).toFixed(1)
      this.renderPage(this.currentPage)
    },
    scaleX() {
      if (this.pdf_scale <= 0.5) return
      this.pdf_scale = +(this.pdf_scale - 0.1).toFixed(1)
      this.renderPage(this.currentPage)
    },
    async loadFile(data) {
      this.pdfDoc = await PDFJS.getDocument(data).promise
      this.pdf_pages = this.pdfDoc.numPages
      this.$nextTick(async () => {
        await this.renderThumbnails()
        this.renderPage(1)
      })
    },
    async renderThumbnails() {
      for (let i = 1; i <= this.pdf_pages; i++) {
        const page = await this.pdfDoc.getPage(i)
        const canvas = document.getElementById('thumbnail_' + i)
        if (!canvas) continue

        const viewport = page.getViewport({ scale: this.thumbnailScale })
        const context = canvas.getContext('2d')

        canvas.height = viewport.height
        canvas.width = viewport.width

        await page.render({
          canvasContext: context,
          viewport: viewport
        }).promise
      }
    },
    async renderPage(num = 1) {
      this.currentPage = num
      const page = await this.pdfDoc.getPage(num)
      const canvas = document.getElementById('the_canvas' + num)
      const ctx = canvas.getContext('2d')
      const dpr = window.devicePixelRatio || 1
      const bsr =
        ctx.webkitBackingStorePixelRatio ||
        ctx.mozBackingStorePixelRatio ||
        ctx.msBackingStorePixelRatio ||
        ctx.oBackingStorePixelRatio ||
        ctx.backingStorePixelRatio ||
        1
      const ratio = dpr / bsr
      const viewport = page.getViewport({ scale: this.pdf_scale })
      canvas.width = viewport.width * ratio
      canvas.height = viewport.height * ratio
      canvas.style.width = viewport.width + 'px'
      this.pdf_div_width = viewport.width + 'px'
      canvas.style.height = viewport.height + 'px'
      ctx.setTransform(ratio, 0, 0, ratio, 0, 0)
      const renderContext = {
        canvasContext: ctx,
        viewport: viewport
      }
      await page.render(renderContext).promise

      // 滚动到当前页面
      this.$nextTick(() => {
        const container = document.querySelector('.pdf-content')
        const activeCanvas = document.querySelector(`#the_canvas${num}`)
        if (container && activeCanvas) {
          activeCanvas.scrollIntoView({ behavior: 'smooth', block: 'center' })
        }

        // 滚动缩略图到可视区域
        const activeThumb = document.querySelector(`#thumbnail_${num}`)
        if (activeThumb) {
          activeThumb.scrollIntoView({ behavior: 'smooth', block: 'center' })
        }
      })
    },
    nextPage() {
      if (this.pdf_pages > this.currentPage) {
        this.renderPage(this.currentPage + 1)
      }
    },
    prePage() {
      if (this.currentPage > 1) {
        this.renderPage(this.currentPage - 1)
      }
    },
    goToPage(page) {
      if (typeof page === 'number' && page >= 1 && page <= this.pdf_pages) {
        this.renderPage(page)
      } else if (typeof page === 'object') {
        // 处理输入框变化事件
        const num = parseInt(page.target.value)
        if (!isNaN(num) && num >= 1 && num <= this.pdf_pages) {
          this.renderPage(num)
        }
      }
    }
  }
}
</script>

<style scoped>
.pdf-viewer-container {
  display: flex;
  height: 100vh;
  overflow: hidden;
}

/* 缩略图侧边栏样式 */
.thumbnail-sidebar {
  width: 200px;
  height: 100vh;
  background-color: #f0f0f0;
  border-right: 1px solid #ddd;
  transition: all 0.3s ease;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.thumbnail-sidebar.collapsed {
  width: 40px;
}

.sidebar-header {
  padding: 10px;
  background-color: #408fff;
  color: white;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.toggle-btn {
  background: none;
  border: none;
  color: white;
  cursor: pointer;
  font-size: 14px;
  padding: 5px;
}

.thumbnail-container {
  flex: 1;
  overflow-y: auto;
  padding: 10px;
}

.thumbnail-item {
  margin-bottom: 15px;
  cursor: pointer;
  position: relative;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
  background-color: white;
}

.thumbnail-item canvas {
  width: 100%;
  height: auto;
  display: block;
}

.page-number {
  position: absolute;
  bottom: 0;
  right: 0;
  background-color: rgba(0, 0, 0, 0.6);
  color: white;
  padding: 2px 6px;
  font-size: 12px;
}

.active-thumbnail {
  outline: 3px solid #408fff;
}

/* 主内容区样式 */
.main-content {
  flex: 1;
  height: 100vh;
  display: flex;
  flex-direction: column;
  transition: margin-left 0.3s ease;
  overflow: hidden;
}

.pdf-nav {
  padding: 10px 20px;
  background-color: #f5f5f5;
  display: flex;
  justify-content: space-between;
  align-items: center;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.nav-controls,
.zoom-controls {
  display: flex;
  align-items: center;
  gap: 10px;
}

.nav-button,
.zoom-button {
  padding: 6px 12px;
  background-color: #408fff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  display: flex;
  align-items: center;
  gap: 5px;
}

.nav-button:disabled,
.zoom-button:disabled {
  background-color: #cccccc;
  cursor: not-allowed;
}

.nav-button:hover:not(:disabled),
.zoom-button:hover:not(:disabled) {
  background-color: #3070d0;
}

.page-info input {
  width: 50px;
  padding: 5px;
  text-align: center;
  border: 1px solid #ddd;
  border-radius: 4px;
}

.zoom-percent {
  min-width: 50px;
  text-align: center;
}

/* PDF内容区样式 */
.pdf-content {
  flex: 1;
  overflow-y: auto;
  padding: 20px;
  margin: 0 auto;
}

.active-page {
  box-shadow: 0 0 10px rgba(64, 143, 255, 0.5);
  margin: 10px 0;
}

.icon {
  font-style: normal;
}
</style>
